﻿// =========================================================================
// THIS CODE-SAMPLE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER 
// EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES 
// OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.

// This sample is not supported under any Microsoft standard support program 
// or service. The code sample is provided AS IS without warranty of any kind. 
// Microsoft further disclaims all implied warranties including, without 
// limitation, any implied warranties of merchantability or of fitness for a 
// particular purpose. The entire risk arising out of the use or performance
// of the sample and documentation remains with you. In no event shall 
// Microsoft, its authors, or anyone else involved in the creation, 
// production, or delivery of the script be liable for any damages whatsoever 
// (including, without limitation, damages for loss of business profits, 
// business interruption, loss of business information, or other pecuniary 
// loss) arising out of  the use of or inability to use the sample or 
// documentation, even if Microsoft has been advised of the possibility of 
// such damages.
//========================================================================= 

using System;
using System.Collections.Generic;
using System.Linq;

using System.Security.Principal;
using System.DirectoryServices.Protocols;
using System.IO;

namespace CodingFromTheField.LdapQueryAnalyzer
{
    public class FilterInfo
    {
        public string Filter { get; set; }

        public string[] Attributes { get; set; }

        public FilterInfo(string filterstring, string[] attributeList)
        {
            Filter = filterstring;

            Attributes = attributeList;
        }

        public override string ToString()
        { return Filter; }
    }

    public class QueryControl
    {
        public int Port = 389;

        public bool PerformPagedQuery = false;

        public ReferralChasingOptions RefOptions = ReferralChasingOptions.None;

        public bool AutoPage = false;

        public bool ExecStatsQuery = false;

        public bool RunAsync = false;

        public bool DoValueRangeRetrieval = false;

        public bool ShowDeleted = false;

        public bool ShowRecycled = false;

        public bool PerformASQ = false;
        
        public bool PerformDirSync = false;

        public bool DirSyncReRun = false;
        public byte[] DirSyncCookie = null;
        public SyncRun DirSyncRun;

        public bool VlvRequired = false;

        public bool SortResults = false;

        public bool SortAscending = true;

        public bool FromGui = false;

        public bool ContainsConstructedAttribute = false;

        public bool MustGetSingleObjectPath = false;
        
        public QUERY_RESULT_EVENT_TYPE CurrentResultEventType = QUERY_RESULT_EVENT_TYPE.NONE;

        public bool PhantomRoot = false;

        public bool RootDse = false;
        public bool QueryExtendedRootDSE = false;

        public int QueryRuns = 0;

        public int PartialRuns = -1;

        public QueryControl() { }

        public bool FirstRun
        {
            get
            {
                if (((QueryExtendedRootDSE) && (QueryRuns == 0)) || (!QueryExtendedRootDSE))
                { return true; }

                else
                { return false; }
            }
        }
    }

    public class SupportedControls
    {
        #region fields

        public List<string> Controls = new List<string> { };

        #endregion

        #region constructor

        internal SupportedControls(object[] controlList)
        { LoadInternal(controlList); }

        #endregion

        #region methods

        private void LoadInternal(object[] controlList)
        { Controls = controlList.Select(v => v.ToString()).ToList(); }

        #endregion
    }

    public class Ports
    {
        public int LDAPPort = 389;

        public int GCPort = 3268;

        public int SelectedPort = 389;

        internal Ports()
        { }

        public int UsePort(bool useGC)
        { return (useGC) ? GCPort : LDAPPort; }
    }

    public class MessageCache
    {
        #region fields

        private List<string> innerMsg = new List<string> { };

        public List<string> DecodedMsg
        {  get { return innerMsg; } }

        public long ResultCount = 0;

        #endregion

        #region constructors

        internal MessageCache(List<string> results, long count)
        {
            innerMsg = results;

            ResultCount = count;
        }

        #endregion

        #region methods

        public void AddMessages(List<string> value, long count)
        {
            ResultCount = count;
            innerMsg.AddRange(value);
        }

        public void InsertMessages(int insertAt, List<string> value)
        { innerMsg.InsertRange(insertAt, value); }

        public void Dispose()
        {
            innerMsg.Clear();
            innerMsg = null;
        }

        #endregion
    }

    public class RangeInfo
    {
        public int Low;

        public int High;

        private int Step;

        public string Name;

        public string FirstRangeName;

        public string CurrentRangeName { get { return String.Format("range={0}-{1}", Low, High); } }

        internal RangeInfo(int lowVal, int maxVal, string orgName, string attributeName)
        {
            Low = lowVal;

            High = maxVal;

            Step = maxVal + 1;

            Name = attributeName;

            FirstRangeName = orgName;
        }

        public string NextRange()
        {
            string ret = null;

            Low += Step;

            High += Step;

            ret = String.Format("{0};range={1}-{2}", Name, Low, High);

            return ret;
        }
    }

    public class HexInfo
    {
        #region fields

        public bool IsGuid = false;

        #endregion

        #region constructor

        internal HexInfo() { }

        #endregion

        #region methods

        public string ToHex(string value, string name)
        {
            string ret = value;

            if (IsGuid)
            { ret = FromGuid(value); }

            return ret;
        }

        public string FromGuid(Guid value)
        {
            string ret = value.ToString();

            byte[] bar = value.ToByteArray();

            ret = FromByte(bar);

            return ret;
        }

        public string FromGuid(string value)
        {
            string ret = value;

            try
            {
                byte[] bar = new Guid(value).ToByteArray();

                ret = FromByte(bar);
            }

            catch (Exception ex)
            { ex.ToDummy(); }

            return ret;
        }

        public string FromSid(SecurityIdentifier value)
        {
            string ret = value.Value;

            byte[] bar = new byte[value.BinaryLength];

            value.GetBinaryForm(bar, 0);

            ret = FromByte(bar);

            return ret;
        }

        public string FromSid(string value)
        {
            string ret = value;

            try
            {

                SecurityIdentifier sid = new SecurityIdentifier(value);

                byte[] bar = new byte[sid.BinaryLength];

                sid.GetBinaryForm(bar, 0);

                ret = FromByte(bar);
            }

            catch (Exception ex)
            { ex.ToDummy(); }

            return ret;
        }

        public string FromNumeric(object value)
        {
            string ret = value.ToString();

            byte[] temp = new byte[] { };

            Type valtype = value.GetType();

            if (valtype.Equals(typeof(sbyte)))
            { temp = BitConverter.GetBytes((sbyte)value); }

            else if (valtype.Equals(typeof(byte)))
            { temp = BitConverter.GetBytes((byte)value); ; }

            else if (valtype.Equals(typeof(short)) || valtype.Equals(typeof(Int16)))
            { temp = BitConverter.GetBytes((short)value); }

            else if (valtype.Equals(typeof(ushort)) || valtype.Equals(typeof(UInt16)))
            { temp = BitConverter.GetBytes((ushort)value); }

            else if (valtype.Equals(typeof(int)) || valtype.Equals(typeof(Int32)))
            { temp = BitConverter.GetBytes((int)value); }

            else if (valtype.Equals(typeof(uint)) || valtype.Equals(typeof(UInt32)))
            { temp = BitConverter.GetBytes((uint)value); }

            else if (valtype.Equals(typeof(long)) || valtype.Equals(typeof(Int64)))
            { temp = BitConverter.GetBytes((long)value); }

            else if (valtype.Equals(typeof(ulong)) || valtype.Equals(typeof(UInt64)))
            { temp = BitConverter.GetBytes((ulong)value); }

            else if (valtype.Equals(typeof(float)) || valtype.Equals(typeof(Single)))
            { temp = BitConverter.GetBytes((float)value); }

            else if (valtype.Equals(typeof(double)))
            { temp = BitConverter.GetBytes((double)value); }

            if (BitConverter.IsLittleEndian)
            { Array.Reverse(temp); }

            byte[] bar = temp;

            ret = FromByte(bar);

            return ret;
        }

        private string FromByte(byte[] value)
        {
            string ret = String.Empty;

            try
            {
                ret = BitConverter.ToString(value, 0);

                ret = "\\" + ret.Replace("-", "\\");
            }

            catch (Exception ex)
            { ex.ToDummy(); }

            return ret;
        }

        #endregion

    }

    public class RootDSEAttributes
    {
        #region fields

        public const string CachePath = "Cache\\Settings";
        public const string FileName = "RootDSE.xml";

        private string[] userOperationalAttributes = new string[] { "approximateHighestInternalObjectID", "dsaVersionString", "dsSchemaAttrCount", 
                                                                        "dsSchemaClassCount", "dsSchemaPrefixCount", "msDS-PortLDAP", 
                                                                        "msDS-PortSSL", "msDS-PrincipalName", "msDS-ReplAllInboundNeighbors", 
                                                                        "msDS-ReplAllOutboundNeighbors", "msDS-ReplConnectionFailures", "msDS-ReplLinkFailures", 
                                                                        "msDS-ReplPendingOps", "msDS-ReplQueueStatistics", "msDS-TopQuotaUsage", 
                                                                        "netlogon", "pendingPropagations", "serviceAccountInfo", 
                                                                        "spnRegistrationResult", "supportedConfigurableSettings", "supportedExtension", 
                                                                        "tokenGroups", "usnAtRifm", "validFSMOs"};

        public List<string> OperationalAttributes
        {
            get { return userOperationalAttributes.ToList(); }
            set { userOperationalAttributes = value.ToArray(); }
        }

        #endregion

        #region constructors

        public RootDSEAttributes() { }

        #endregion

        #region methods

        public static RootDSEAttributes Load()
        {
            RootDSEAttributes ret = new RootDSEAttributes();

            string filepath = GetFilePath();

            string sertext = string.Empty;

            if (!File.Exists(filepath))
            {
                sertext = ret.SerializeThis();

                sertext.WriteToFile(filepath, false);
            }

            else
            {
                filepath.ReadFromFile(out sertext);

                sertext.DeSerializeFromString(out ret);
            }

            return ret;
        }

        private static string GetFilePath()
        {
            string ret = string.Empty;

            bool success;

            ret = GlobalHelper.PathInCurrentDirectory(CachePath, out success);

            ret = Path.Combine(ret, FileName);

            return ret;
        }

        #endregion
    }
}
